package com.atguigu.srb.core.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.atguigu.srb.base.exception.SrbBussinessException;
import com.atguigu.srb.base.result.ResponseEnum;
import com.atguigu.srb.core.listener.DictExcelDataListener;
import com.atguigu.srb.core.pojo.data.DictData;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.service.DictService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2023-01-04
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
    @Resource
    RedisTemplate redisTemplate;
    @Override
    public void exportDicts(HttpServletResponse response) {
        try {
            //设置响应报文的头： content-disposition  表示响应体内容为一个附件
            response.setHeader("content-disposition",
                    "attachment;filename=dicts_"+
                            new DateTime().toString("yyyy_MM_dd")
                            + ExcelTypeEnum.XLSX.getValue());
            //设置响应体内容： 将数据字典数据查询后设置到excel文件中 再设置到响应体中
            List<Dict> dicts = baseMapper.selectList(null);
            //将dicts转为DictData对象的集合 按照DictData类的配置写入到excel文件中
            List<DictData> dictDataList = dicts.stream().map(dict -> {
                DictData dictData = new DictData();
                dictData.setId(dict.getId());
                dictData.setCode(dict.getDictCode());
                dictData.setParentId(dict.getParentId());
                dictData.setTitle(dict.getName());
                dictData.setValue(dict.getValue());
                return dictData;
            }).collect(Collectors.toList());
            //使用EasyExcel 向response的响应体输出流中写入数据
            EasyExcel.write(response.getOutputStream())
                    .sheet("数据字典")
                    .head(DictData.class)
                    .doWrite(dictDataList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void importDicts(MultipartFile excel) {
        try {
            EasyExcel.read(excel.getInputStream()) //获取上传的excel文件流进行读取
                    .excelType(ExcelTypeEnum.XLSX)
                    .head(DictData.class) //要读取的excel文件映射的类型
                    .registerReadListener(new DictExcelDataListener(baseMapper)) // 解析读取到数据的监听器
                    .doReadAll();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //数据字典数据一般不会修改，查询较多
    //可以使用缓存管理
    // value和key用来拼接 缓存的key：value写字符串前缀，key可使用springEL表达式获取参数
    @Cacheable(value = "dicts:cache" , key = "{#pid}" )   //当前查询方法执行时需要缓存管理
    @Override
    public List<Dict> getDictsByParentId(String pid) {
        //1、判断redis中如果有缓存 获取返回
//        Object o = redisTemplate.opsForValue().get("dict:cache:" + pid);
//        if(o!=null){
//            System.out.println("查询时走了缓存..");
//            return (List<Dict>) o;
//        }
        //2、如果没有缓存 查询数据库 存到redis中 返回数据
        // 前端展示数据字典时，需要判断数据字典是否有下一级 便于懒加载
        List<Dict> dicts = this.list(Wrappers.lambdaQuery(Dict.class)
                .eq(Dict::getParentId, pid));
        //遍历dicts集合，为每个dict对象查询设置hasChildren属性值
        dicts.forEach(dict->{
            //使用正在遍历的数据字典的id 当做parentid查询下一级 如果有代表有下一级
            int count = this.count(Wrappers.lambdaQuery(Dict.class)
                    .eq(Dict::getParentId, dict.getId()));
            dict.setHasChildren(count>0);
        });
        System.out.println("查询时走了mysql数据库..");
//        redisTemplate.opsForValue().set("dict:cache:" + pid,dicts ,
//                600, TimeUnit.SECONDS);

        return dicts;
    }

    @Override
    public void deleteById(String id) {
        int count = this.count(Wrappers.lambdaQuery(Dict.class)
                .eq(Dict::getParentId, id));
       if(count!=0){
            throw new SrbBussinessException(ResponseEnum.DICT_DEL_ERROR);
       }
       this.removeById(id);
    }

    @Override
    public Dict getDictByDictCodeAndValue(String dictCode, Integer value) {
        return baseMapper.selectDictByDictCodeAndValue(dictCode,value);
    }
}
